/*!
 * \file WtRunner.cpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief WonderTrader运行器类实现文件
 *		  本文件实现了WtRunner运行器类的所有方法
 *		  提供完整的交易系统生命周期管理功能
 *		  支持CTA、HFT、SEL三种交易引擎的初始化和运行
 *		  集成行情解析、交易适配、策略管理、数据管理等核心组件
 *		  实现跨平台信号处理和异常安全的系统运行框架
 */
#include "WtRunner.h"

#include "../WtCore/WtHelper.h"
#include "../WtCore/CtaStraContext.h"
#include "../WtCore/HftStraContext.h"

#include "../Includes/WTSVariant.hpp"
#include "../WTSTools/WTSLogger.h"
#include "../WTSUtils/WTSCfgLoader.h"
#include "../WTSUtils/SignalHook.hpp"
#include "../Share/StrUtil.hpp"


/**
 * @brief 获取程序二进制文件目录
 * @return 返回程序安装目录路径
 * @details 获取当前程序的安装目录路径
 *          使用boost::filesystem获取初始路径
 *          路径会被标准化处理，确保跨平台兼容性
 *          结果会被缓存，避免重复计算
 */
const char* getBinDir()
{
	static std::string basePath;
	if (basePath.empty())
	{
		basePath = boost::filesystem::initial_path<boost::filesystem::path>().string();

		basePath = StrUtil::standardisePath(basePath);
	}

	return basePath.c_str();
}



/**
 * @brief 构造函数
 * @details 初始化WtRunner实例，设置默认状态：
 *          - _data_store: 数据存储指针初始化为NULL
 *          - _is_hft: HFT模式标志初始化为false
 *          - _is_sel: SEL模式标志初始化为false
 *          
 *          根据编译平台安装信号处理钩子：
 *          - Windows平台：禁用信号钩子
 *          - Unix/Linux平台：启用信号钩子，捕获系统信号并记录日志
 */
WtRunner::WtRunner()
	: _data_store(NULL)
	, _is_hft(false)
	, _is_sel(false)
{
#if _WIN32
// Signal hooks disabled in WIN32
#else
// Signal hooks enabled in UNIX
	install_signal_hooks([](const char* message) {
		WTSLogger::error(message);
	});
#endif
}


/**
 * @brief 析构函数
 * @details 清理WtRunner资源
 *          释放相关内存和资源
 *          各个组件会在其析构函数中自动清理
 */
WtRunner::~WtRunner()
{
}

/**
 * @brief 初始化系统
 * @return 成功返回true，失败返回false
 * @details 执行系统基础初始化操作：
 *          1. 初始化日志系统
 *             - 优先加载logcfg.json配置文件
 *             - 如果不存在则尝试logcfg.yaml
 *          2. 设置程序安装目录
 *             - 通过WtHelper设置全局安装目录
 *             - 用于后续模块路径解析
 */
bool WtRunner::init()
{
	std::string path = "logcfg.json";
	if(!StdFile::exists(path.c_str()))
		path = "logcfg.yaml";
	WTSLogger::init(path.c_str());

	WtHelper::setInstDir(getBinDir());

	return true;
}

/**
 * @brief 配置系统
 * @return 成功返回true，失败返回false
 * @details 加载和配置系统各个组件，执行以下步骤：
 *          1. 加载主配置文件（config.json/yaml）
 *          2. 加载基础数据文件（交易时段、品种、合约、节假日、主力合约等）
 *          3. 初始化交易引擎（根据配置选择CTA/HFT/SEL）
 *          4. 初始化数据管理器
 *          5. 初始化动作策略管理器
 *          6. 初始化行情解析器（支持配置文件或数组配置）
 *          7. 初始化交易适配器（支持配置文件或数组配置）
 *          8. 初始化事件通知器
 *          9. 初始化执行器（仅非HFT模式）
 *          10. 初始化交易策略（根据引擎类型选择CTA或HFT策略）
 */
bool WtRunner::config()
{
	std::string cfgFile = "config.json";
	if (!StdFile::exists(cfgFile.c_str()))
		cfgFile = "config.yaml";

	_config = WTSCfgLoader::load_from_file(cfgFile, true);
	if(_config == NULL)
	{
		WTSLogger::error_f("Loading config file {} failed", cfgFile);
		return false;
	}

	// 加载基础数据文件
	WTSVariant* cfgBF = _config->get("basefiles");
	bool isUTF8 = cfgBF->getBoolean("utf-8");
	if (cfgBF->get("session"))
		_bd_mgr.loadSessions(cfgBF->getCString("session"), isUTF8);

	WTSVariant* cfgItem = cfgBF->get("commodity");
	if (cfgItem)
	{
		if (cfgItem->type() == WTSVariant::VT_String)
		{
			_bd_mgr.loadCommodities(cfgItem->asCString(), isUTF8);
		}
		else if (cfgItem->type() == WTSVariant::VT_Array)
		{
			for (uint32_t i = 0; i < cfgItem->size(); i++)
			{
				_bd_mgr.loadCommodities(cfgItem->get(i)->asCString(), isUTF8);
			}
		}
	}

	cfgItem = cfgBF->get("contract");
	if (cfgItem)
	{
		if (cfgItem->type() == WTSVariant::VT_String)
		{
			_bd_mgr.loadContracts(cfgItem->asCString(), isUTF8);
		}
		else if (cfgItem->type() == WTSVariant::VT_Array)
		{
			for (uint32_t i = 0; i < cfgItem->size(); i++)
			{
				_bd_mgr.loadContracts(cfgItem->get(i)->asCString(), isUTF8);
			}
		}
	}

	if (cfgBF->get("holiday"))
		_bd_mgr.loadHolidays(cfgBF->getCString("holiday"));

	if (cfgBF->get("hot"))
		_hot_mgr.loadHots(cfgBF->getCString("hot"));

	if (cfgBF->get("second"))
		_hot_mgr.loadSeconds(cfgBF->getCString("second"));

	// 初始化交易引擎
	initEngine();

	// 初始化数据管理器
	initDataMgr();

	if (!initActionPolicy())
		return false;

	// 初始化行情通道
	WTSVariant* cfgParser = _config->get("parsers");
	if (cfgParser)
	{
		if (cfgParser->type() == WTSVariant::VT_String)
		{
			const char* filename = cfgParser->asCString();
			if (StdFile::exists(filename))
			{
				WTSLogger::info_f("Reading parser config from {}...", filename);
				WTSVariant* var = WTSCfgLoader::load_from_file(filename, isUTF8);
				if(var)
				{
					if (!initParsers(var->get("parsers")))
						WTSLogger::error("Loading parsers failed");
					var->release();
				}
				else
				{
					WTSLogger::error_f("Loading parser config {} failed", filename);
				}
			}
			else
			{
				WTSLogger::error_f("Parser configuration {} not exists", filename);
			}
		}
		else if (cfgParser->type() == WTSVariant::VT_Array)
		{
			initParsers(cfgParser);
		}
	}

	// 初始化交易通道
	WTSVariant* cfgTraders = _config->get("traders");
	if (cfgTraders)
	{
		if (cfgTraders->type() == WTSVariant::VT_String)
		{
			const char* filename = cfgTraders->asCString();
			if (StdFile::exists(filename))
			{
				WTSLogger::info_f("Reading trader config from {}...", filename);
				WTSVariant* var = WTSCfgLoader::load_from_file(filename, isUTF8);
				if (var)
				{
					if (!initTraders(var->get("traders")))
						WTSLogger::error("Loading traders failed");
					var->release();
				}
				else
				{
					WTSLogger::error_f("Loading trader config {} failed", filename);
				}
			}
			else
			{
				WTSLogger::error("Trader configuration %s not exists", filename);
			}
		}
		else if (cfgTraders->type() == WTSVariant::VT_Array)
		{
			initTraders(cfgTraders);
		}
	}

	initEvtNotifier();

	// 如果不是高频模式，则需要加载执行模块
	if (!_is_hft)
	{
		WTSVariant* cfgExec = _config->get("executers");
		if (cfgExec != NULL)
		{
			if (cfgExec->type() == WTSVariant::VT_String)
			{
				const char* filename = cfgExec->asCString();
				if (StdFile::exists(filename))
				{
					WTSLogger::info_f("Reading executer config from {}...", filename);
					WTSVariant* var = WTSCfgLoader::load_from_file(filename, isUTF8);
					if (var)
					{
						if (!initExecuters(var->get("executers")))
							WTSLogger::error("Loading executers failed");
						var->release();
					}
					else
					{
						WTSLogger::error_f("Loading executer config {} failed", filename);
					}
				}
				else
				{
					WTSLogger::error("Trader configuration %s not exists", filename);
				}
			}
			else if (cfgExec->type() == WTSVariant::VT_Array)
			{
				initExecuters(cfgExec);
			}
		}

	}

	if (!_is_hft)
		initCtaStrategies();
	else
		initHftStrategies();
	
	return true;
}

/**
 * @brief 初始化CTA策略
 * @return 成功返回true，失败返回false
 * @details 加载和初始化所有CTA策略：
 *          1. 从配置中获取CTA策略配置数组
 *          2. 从cta/目录加载策略工厂
 *          3. 遍历配置，为每个活跃策略：
 *             - 创建策略实例
 *             - 初始化策略参数
 *             - 创建策略上下文
 *             - 绑定策略到上下文
 *             - 添加上下文到CTA引擎
 */
bool WtRunner::initCtaStrategies()
{
	WTSVariant* cfg = _config->get("strategies");
	if (cfg == NULL || cfg->type() != WTSVariant::VT_Object)
		return false;

	cfg = cfg->get("cta");
	if (cfg == NULL || cfg->type() != WTSVariant::VT_Array)
		return false;

	std::string path = WtHelper::getCWD() + "cta/";
	_cta_stra_mgr.loadFactories(path.c_str());

	for (uint32_t idx = 0; idx < cfg->size(); idx++)
	{
		WTSVariant* cfgItem = cfg->get(idx);
		if (!cfgItem->getBoolean("active"))
			continue;

		const char* id = cfgItem->getCString("id");
		const char* name = cfgItem->getCString("name");
		CtaStrategyPtr stra = _cta_stra_mgr.createStrategy(name, id);
		stra->self()->init(cfgItem->get("params"));
		CtaStraContext* ctx = new CtaStraContext(&_cta_engine, id);
		ctx->set_strategy(stra->self());
		_cta_engine.addContext(CtaContextPtr(ctx));
	}

	return true;
}

/**
 * @brief 初始化HFT策略
 * @return 成功返回true，失败返回false
 * @details 加载和初始化所有HFT策略：
 *          1. 从配置中获取HFT策略配置数组
 *          2. 从hft/目录加载策略工厂
 *          3. 遍历配置，为每个活跃策略：
 *             - 创建策略实例
 *             - 初始化策略参数
 *             - 创建策略上下文（支持代理模式）
 *             - 绑定策略到上下文
 *             - 绑定交易适配器到上下文
 *             - 添加上下文到HFT引擎
 */
bool WtRunner::initHftStrategies()
{
	WTSVariant* cfg = _config->get("strategies");
	if (cfg == NULL || cfg->type() != WTSVariant::VT_Object)
		return false;

	cfg = cfg->get("hft");
	if (cfg == NULL || cfg->type() != WTSVariant::VT_Array)
		return false;

	std::string path = WtHelper::getCWD() + "hft/";
	_hft_stra_mgr.loadFactories(path.c_str());

	for (uint32_t idx = 0; idx < cfg->size(); idx++)
	{
		WTSVariant* cfgItem = cfg->get(idx);
		if (!cfgItem->getBoolean("active"))
			continue;

		const char* id = cfgItem->getCString("id");
		const char* name = cfgItem->getCString("name");
		bool agent = cfgItem->getBoolean("agent");
		HftStrategyPtr stra = _hft_stra_mgr.createStrategy(name, id);
		if (stra == NULL)
			continue;

		stra->self()->init(cfgItem->get("params"));
		HftStraContext* ctx = new HftStraContext(&_hft_engine, id, agent);
		ctx->set_strategy(stra->self());

		const char* traderid = cfgItem->getCString("trader");
		TraderAdapterPtr trader = _traders.getAdapter(traderid);
		if(trader)
		{
			ctx->setTrader(trader.get());
			trader->addSink(ctx);
		}
		else
		{
			WTSLogger::error("Trader %s not exists, binding trader to HFT strategy failed", traderid);
		}

		_hft_engine.addContext(HftContextPtr(ctx));
	}

	return true;
}


/**
 * @brief 初始化交易引擎
 * @return 成功返回true，失败返回false
 * @details 根据配置选择并初始化对应的交易引擎：
 *          1. 从环境配置中获取引擎类型
 *          2. 根据引擎名称设置模式标志：
 *             - 空或"cta": CTA模式
 *             - "sel": SEL选股模式
 *             - "hft": HFT高频模式
 *          3. 初始化对应引擎并设置为当前引擎
 *          4. 绑定交易适配器管理器到引擎
 */
bool WtRunner::initEngine()
{
	WTSVariant* cfg = _config->get("env");
	if (cfg == NULL)
		return false;

	const char* name = cfg->getCString("name");
	
	if (strlen(name) == 0 || wt_stricmp(name, "cta") == 0)
	{
		_is_hft = false;
		_is_sel = false;
	}
	else if (wt_stricmp(name, "sel") == 0)
	{
		_is_sel = true;
	}
	else //if (wt_stricmp(name, "hft") == 0)
	{
		_is_hft = true;
	}

	if (_is_hft)
	{
		WTSLogger::info("Trading enviroment initialzied with engine: HFT");
		_hft_engine.init(cfg, &_bd_mgr, &_data_mgr, &_hot_mgr, &_notifier);
		_engine = &_hft_engine;
	}
	else if (_is_sel)
	{
		WTSLogger::info("Trading enviroment initialzied with engine: SEL");
		_sel_engine.init(cfg, &_bd_mgr, &_data_mgr, &_hot_mgr, &_notifier);
		_engine = &_sel_engine;
	}
	else
	{
		WTSLogger::info("Trading enviroment initialzied with engine: CTA");
		_cta_engine.init(cfg, &_bd_mgr, &_data_mgr, &_hot_mgr, &_notifier);
		_engine = &_cta_engine;
	}

	_engine->set_adapter_mgr(&_traders);

	return true;
}

/**
 * @brief 初始化动作策略管理器
 * @return 成功返回true，失败返回false
 * @details 初始化买卖动作策略管理器
 *          从配置中获取bspolicy配置文件路径
 *          加载买卖动作规则配置
 */
bool WtRunner::initActionPolicy()
{
	return _act_policy.init(_config->getCString("bspolicy"));
}

/**
 * @brief 初始化数据管理器
 * @return 成功返回true，失败返回false
 * @details 初始化数据管理器：
 *          1. 从配置中获取数据配置
 *          2. 使用配置和引擎初始化数据管理器
 *          3. 记录初始化完成日志
 */
bool WtRunner::initDataMgr()
{
	WTSVariant*cfg = _config->get("data");
	if (cfg == NULL)
		return false;

	_data_mgr.init(cfg, _engine);
	WTSLogger::info("Data manager initialized");

	return true;
}

/**
 * @brief 初始化行情解析器
 * @param cfgParser 行情解析器配置数组
 * @return 成功返回true，失败返回false
 * @details 根据配置初始化所有行情解析器：
 *          1. 遍历配置数组中的每个解析器配置
 *          2. 跳过非活跃的解析器
 *          3. 为每个解析器：
 *             - 获取或生成解析器ID
 *             - 创建解析器适配器
 *             - 初始化适配器
 *             - 添加到解析器管理器
 *          4. 记录加载的解析器数量
 */
bool WtRunner::initParsers(WTSVariant* cfgParser)
{
	if (cfgParser == NULL)
		return false;

	uint32_t count = 0;
	for (uint32_t idx = 0; idx < cfgParser->size(); idx++)
	{
		WTSVariant* cfgItem = cfgParser->get(idx);
		if(!cfgItem->getBoolean("active"))
			continue;

		const char* id = cfgItem->getCString("id");
		// By Wesley @ 2021.12.14
		// 如果id为空，则自动生成id
		std::string realid = id;
		if (realid.empty())
		{
			static uint32_t auto_parserid = 1000;
			realid = StrUtil::printf("auto_parser_%u", auto_parserid++);
		}

		ParserAdapterPtr adapter(new ParserAdapter);
		adapter->init(realid.c_str(), cfgItem, _engine, &_bd_mgr, &_hot_mgr);
		_parsers.addAdapter(realid.c_str(), adapter);

		count++;
	}

	WTSLogger::info("%u parsers loaded", count);
	return true;
}

/**
 * @brief 初始化执行器
 * @param cfgExecuter 执行器配置数组
 * @return 成功返回true，失败返回false
 * @details 初始化本地和分布式执行器：
 *          1. 从executer/目录加载执行器工厂
 *          2. 遍历配置数组中的每个执行器配置
 *          3. 跳过非活跃的执行器
 *          4. 根据local标志创建对应类型的执行器：
 *             - 本地执行器：绑定交易适配器，支持本地执行
 *             - 分布式执行器：支持远程执行
 *          5. 添加执行器到CTA引擎
 *          6. 记录加载的执行器数量
 */
bool WtRunner::initExecuters(WTSVariant* cfgExecuter)
{
	if (cfgExecuter == NULL || cfgExecuter->type() != WTSVariant::VT_Array)
		return false;

	std::string path = WtHelper::getCWD() + "executer/";
	_exe_factory.loadFactories(path.c_str());

	uint32_t count = 0;
	for (uint32_t idx = 0; idx < cfgExecuter->size(); idx++)
	{
		WTSVariant* cfgItem = cfgExecuter->get(idx);
		if (!cfgItem->getBoolean("active"))
			continue;

		const char* id = cfgItem->getCString("id");
		bool bLocal = cfgItem->getBoolean("local");

		if (bLocal)
		{
			WtLocalExecuter* executer = new WtLocalExecuter(&_exe_factory, id, &_data_mgr);
			if (!executer->init(cfgItem))
				return false;

			TraderAdapterPtr trader = _traders.getAdapter(cfgItem->getCString("trader"));
			executer->setTrader(trader.get());
			trader->addSink(executer);

			_cta_engine.addExecuter(ExecCmdPtr(executer));
		}
		else
		{
			WtDistExecuter* executer = new WtDistExecuter(id);
			if (!executer->init(cfgItem))
				return false;

			_cta_engine.addExecuter(ExecCmdPtr(executer));
		}
		count++;
	}

	WTSLogger::info("%u executers loaded", count);

	return true;
}

/**
 * @brief 初始化交易适配器
 * @param cfgTrader 交易适配器配置数组
 * @return 成功返回true，失败返回false
 * @details 根据配置初始化所有交易适配器：
 *          1. 遍历配置数组中的每个交易适配器配置
 *          2. 跳过非活跃的适配器
 *          3. 为每个适配器：
 *             - 创建交易适配器实例
 *             - 初始化适配器（绑定事件通知器、基础数据管理器、动作策略）
 *             - 添加到交易适配器管理器
 *          4. 记录加载的适配器数量
 */
bool WtRunner::initTraders(WTSVariant* cfgTrader)
{
	if (cfgTrader == NULL || cfgTrader->type() != WTSVariant::VT_Array)
		return false;
	
	uint32_t count = 0;
	for (uint32_t idx = 0; idx < cfgTrader->size(); idx++)
	{
		WTSVariant* cfgItem = cfgTrader->get(idx);
		if (!cfgItem->getBoolean("active"))
			continue;

		const char* id = cfgItem->getCString("id");

		TraderAdapterPtr adapter(new TraderAdapter(&_notifier));
		adapter->init(id, cfgItem, &_bd_mgr, &_act_policy);

		_traders.addAdapter(id, adapter);

		count++;
	}

	WTSLogger::info("%u traders loaded", count);

	return true;
}

/**
 * @brief 运行系统
 * @param bAsync 是否异步运行，默认为false
 * @details 启动整个交易系统：
 *          1. 启动行情解析器管理器
 *          2. 启动交易适配器管理器
 *          3. 启动交易引擎
 *          
 *          使用异常处理确保系统稳定性
 *          如果bAsync为true，则异步运行；否则阻塞运行
 */
void WtRunner::run(bool bAsync /* = false */)
{
	try
	{
		_parsers.run();
		_traders.run();

		_engine->run(bAsync);
	}
	catch (...)
	{
		//print_stack_trace([](const char* message) {
		//	WTSLogger::error(message);
		//});
	}
}

/// 日志级别标签数组，用于日志级别到字符串的转换
const char* LOG_TAGS[] = {
	"all",
	"debug",
	"info",
	"warn",
	"error",
	"fatal",
	"none"
};

/**
 * @brief 处理日志追加
 * @param ll 日志级别
 * @param msg 日志消息
 * @details 实现ILogHandler接口，处理系统日志：
 *          1. 将日志级别转换为字符串标签
 *          2. 通过事件通知器转发日志消息
 *          3. 支持外部日志监听和处理
 */
void WtRunner::handleLogAppend(WTSLogLevel ll, const char* msg)
{
	_notifier.notifyLog(LOG_TAGS[ll - 100], msg);
}

/**
 * @brief 初始化事件通知器
 * @return 成功返回true，失败返回false
 * @details 初始化事件通知系统：
 *          1. 从配置中获取通知器配置
 *          2. 验证配置格式（必须为对象类型）
 *          3. 使用配置初始化事件通知器
 *          4. 配置事件回调和通知机制
 */
bool WtRunner::initEvtNotifier()
{
	WTSVariant* cfg = _config->get("notifier");
	if (cfg == NULL || cfg->type() != WTSVariant::VT_Object)
		return false;

	_notifier.init(cfg);

	return true;
}